package com.study.tx.annotation.service;

import com.study.tx.common.dao.OrderDao;
import com.study.tx.common.dao.OrderItemDao;
import com.study.tx.common.entity.Order;
import com.study.tx.common.entity.OrderItem;
import com.study.tx.common.service.OrderItemService;
import com.study.tx.common.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 订单接口的实现
 *
 * @author doveylovey
 * @version v1.0.0
 * @email 1135782208@qq.com
 * @date 2021年02月02日
 */
@Slf4j
@Service("annotationOrderService")
public class AnnotationOrderServiceImpl implements OrderService {
    @Resource
    private OrderDao annotationOrderDao;
    @Resource
    private OrderItemDao annotationOrderItemDao;
    @Resource
    private OrderItemService annotationOrderItemService;
    @Resource
    private TransactionTemplate transactionTemplate;
    @Resource
    private PlatformTransactionManager transactionManager;
    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    private Order buildOrder(Long userId) {
        LocalDateTime now = LocalDateTime.now();
        Order order = new Order();
        order.setUserId(userId);
        order.setOrderStatus(1);
        order.setPayType(1);
        order.setPayMoney(BigDecimal.TEN);
        order.setGmtCreate(now);
        order.setGmtUpdate(now);
        return order;
    }

    private OrderItem buildOrderItem(Order order, Long productId) {
        OrderItem orderItem = new OrderItem();
        orderItem.setOrderId(order.getOrderId());
        orderItem.setUserId(order.getUserId());
        orderItem.setProductId(productId);
        orderItem.setProductName("商品名称-" + productId);
        orderItem.setProductPrice(BigDecimal.ONE);
        orderItem.setPurchaseCount(10);
        orderItem.setPayMoney(BigDecimal.TEN);
        return orderItem;
    }

    @Override
    public String truncateOrder() {
        int truncateOrder = annotationOrderDao.truncateOrder();
        log.info("清空 t_order 表结果：{}", truncateOrder);
        int truncateOrderItem = annotationOrderItemService.truncateOrderItem();
        return "truncateOrder=" + truncateOrder + "，truncateOrderItem=" + truncateOrderItem;
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    @Override
    public String insert(Long userId, Long productId) {
        Order order = this.buildOrder(userId);
        int result4Order = annotationOrderDao.insert(order);
        System.out.println("操作 t_order 结果：" + result4Order);
        /*if (true) {
            throw new RuntimeException("操作 t_order 之后、 t_order_item 之前抛出了异常！");
        }*/
        int result4OrderItem = 0;
        //result4OrderItem = annotationOrderItemService.insert(order, productId);
        result4OrderItem = this.insert(order, productId);
        /*try {
            result4OrderItem = annotationOrderItemService.insert(order, productId);
        } catch (Exception e) {
            System.err.println("捕获到了异常！" + e);
        }*/
        /*try {
            result4OrderItem = annotationOrderItemService.insert(order, productId);
        } catch (Exception e) {
            throw new RuntimeException("捕获到了异常后再次抛出异常！");
        }*/
        /*if (true) {
            throw new RuntimeException("操作 t_order 之后、 t_order_item 之后抛出了异常！");
        }*/
        // 发送消息到 MQ
        /*TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void beforeCommit(boolean readOnly) {
                log.info("调用了 beforeCommit() 方法，readOnly={}，参数：{}", readOnly, JSON.toJSONString(order));
            }

            @Override
            public void afterCommit() {
                // 当数据成功保存到数据库中并且事务提交了，就发送消息到 MQ 中
                log.info("调用了 afterCommit() 方法，参数：{}", JSON.toJSONString(order));
            }

            @Override
            public void beforeCompletion() {
                log.info("调用了 beforeCompletion() 方法，参数：{}", JSON.toJSONString(order));
            }

            @Override
            public void afterCompletion(int status) {
                log.info("调用了 afterCompletion() 方法，status={}，参数：{}", status, JSON.toJSONString(order));
            }
        });*/
        // 发布一个自定义的事件
        /*applicationEventPublisher.publishEvent(new MyOrderTransactionEvent("操作 t_order 的事务事件，请事务提交后执行我~~~", order));
        if (userId == null) {
            // 如果代码未发生异常，由于业务不满足某条件而需要回滚时，有两种解决方法：抛出自定义异常(常用)、通过编程代码回滚(不常用)
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }*/
        return "result4Order=" + result4Order + "，result4OrderItem=" + result4OrderItem;
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    @Override
    public Integer insert(Order order, Long productId) {
        OrderItem orderItem = this.buildOrderItem(order, productId);
        int result = annotationOrderItemDao.insert(orderItem);
        System.out.println("操作 t_order_item 结果：" + result);
        if (true) {
            throw new RuntimeException("操作 t_order_item 之前抛出了异常！");
        }
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer update(Order order) {
        return annotationOrderDao.update(order);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer delete(Long orderId) {
        return annotationOrderDao.delete(orderId);
    }

    @Transactional(readOnly = true)
    @Override
    public List<Order> findByUserId(Long userId) {
        return annotationOrderDao.findByUserId(userId);
    }

    @Override
    public void transactionTemplateWithoutResult(Long userId, Long productId) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                try {
                    // 业务代码
                    Order order = buildOrder(userId);
                    int result4Order = annotationOrderDao.insert(order);
                    System.out.println("操作 t_order 结果：" + result4Order);
                    annotationOrderItemService.transactionTemplateWithoutResult(order, productId);
                } catch (Exception e) {
                    // 回滚
                    transactionStatus.setRollbackOnly();
                }
            }
        });
    }

    @Override
    public String transactionTemplateWithResult(Long userId, Long productId) {
        String result = transactionTemplate.execute(new TransactionCallback<String>() {
            @Override
            public String doInTransaction(TransactionStatus transactionStatus) {
                try {
                    // 业务代码
                    Order order = buildOrder(userId);
                    int result4Order = annotationOrderDao.insert(order);
                    System.out.println("操作 t_order 结果：" + result4Order);
                    int result4OrderItem = annotationOrderItemService.transactionTemplateWithResult(order, productId);
                    return "result4Order=" + result4Order + "，result4OrderItem=" + result4OrderItem;
                } catch (Exception e) {
                    // 回滚
                    transactionStatus.setRollbackOnly();
                    return null;
                }
            }
        });
        return result;
    }

    @Override
    public void transactionManagerWithoutResult(Long userId, Long productId) {
        // 定义事务属性
        DefaultTransactionDefinition transDef = new DefaultTransactionDefinition();
        // 设置传播行为属性
        transDef.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED);
        // 获得事务状态
        TransactionStatus status = transactionManager.getTransaction(transDef);
        try {
            // 业务代码
            Order order = this.buildOrder(userId);
            int result4Order = annotationOrderDao.insert(order);
            System.out.println("操作 t_order 结果：" + result4Order);
            annotationOrderItemService.transactionManagerWithoutResult(order, productId);
            // 提交
            transactionManager.commit(status);
        } catch (Exception e) {
            // 回滚
            transactionManager.rollback(status);
        }
    }

    @Override
    public String transactionManagerWithResult(Long userId, Long productId) {
        // 定义事务属性
        DefaultTransactionDefinition transDef = new DefaultTransactionDefinition();
        // 设置传播行为属性
        transDef.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED);
        // 获得事务状态
        TransactionStatus status = transactionManager.getTransaction(transDef);
        try {
            // 业务代码
            Order order = this.buildOrder(userId);
            int result4Order = annotationOrderDao.insert(order);
            System.out.println("操作 t_order 结果：" + result4Order);
            int result4OrderItem = annotationOrderItemService.transactionManagerWithResult(order, productId);
            // 提交
            transactionManager.commit(status);
            return "result4Order=" + result4Order + "，result4OrderItem=" + result4OrderItem;
        } catch (Exception e) {
            // 回滚
            transactionManager.rollback(status);
            return null;
        }
    }
}
